package cn.topcode.unicorn.wxsdk.wxpay;

import cn.topcode.unicorn.utils.*;
import cn.topcode.unicorn.utils.http.HttpResp;
import cn.topcode.unicorn.utils.http.HttpUtil;
import cn.topcode.unicorn.wxsdk.wxpay.dto.closeorder.CloseOrder;
import cn.topcode.unicorn.wxsdk.wxpay.dto.closeorder.CloseOrderResult;
import cn.topcode.unicorn.wxsdk.wxpay.dto.downloadbill.DownloadBill;
import cn.topcode.unicorn.wxsdk.wxpay.dto.downloadbill.DownloadBillResult;
import cn.topcode.unicorn.wxsdk.wxpay.dto.orderquery.OrderQuery;
import cn.topcode.unicorn.wxsdk.wxpay.dto.orderquery.OrderQueryResult;
import cn.topcode.unicorn.wxsdk.wxpay.dto.refund.Refund;
import cn.topcode.unicorn.wxsdk.wxpay.dto.refund.RefundResult;
import cn.topcode.unicorn.wxsdk.wxpay.dto.refundquery.RefundQuery;
import cn.topcode.unicorn.wxsdk.wxpay.dto.refundquery.RefundQueryResult;
import cn.topcode.unicorn.wxsdk.wxpay.dto.report.Report;
import cn.topcode.unicorn.wxsdk.wxpay.dto.report.ReportResult;
import cn.topcode.unicorn.wxsdk.wxpay.dto.unifiedorder.PrepayInfo;
import cn.topcode.unicorn.wxsdk.wxpay.dto.unifiedorder.SceneInfo;
import cn.topcode.unicorn.wxsdk.wxpay.dto.unifiedorder.UnifiedOrder;
import cn.topcode.unicorn.wxsdk.wxpay.dto.unifiedorder.UnifiedOrderResult;
import com.alibaba.fastjson.annotation.JSONField;
import com.thoughtworks.xstream.annotations.XStreamAlias;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Unicorn on 2017/12/28.
 */
public class WxPayInvoker {

    /**
     * 统一下单地址
     */
    public static final String URL_UNIFIED_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    /**
     * 订单查询地址
     */
    public static final String URL_ORDER_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";

    /**
     * 关闭订单地址
     */
    public static final String URL_CLOSE_ORDER = "https://api.mch.weixin.qq.com/pay/closeorder";

    /**
     * 申请退款地址
     */
    public static final String URL_REFUND = "https://api.mch.weixin.qq.com/secapi/pay/refund";

    /**
     * 退款查询地址
     */
    public static final String URL_REFUND_QUERY = "https://api.mch.weixin.qq.com/pay/refundquery";

    /**
     * 下载对账单地址
     */
    public static final String URL_DOWNLOAD_BILL = "https://api.mch.weixin.qq.com/pay/downloadbill";


    /**
     * 交易保障地址
     */
    public static final String URL_REPORT = "https://api.mch.weixin.qq.com/payitil/report";

    /**
     * 拉取订单评价数据地址
     */
    public static final String URL_ORDER_COMMENT_QUERY = "https://api.mch.weixin.qq.com/billcommentsp/batchquerycomment";


    /**
     * 统一下单
     *
     * @param unifiedOrder
     * @return
     */
    public static PrepayInfo unifiedOrder(UnifiedOrder unifiedOrder, SceneInfo sceneInfo, String key) {
        if(sceneInfo != null) {
            unifiedOrder.setSceneInfo(JsonUtil.toJson(sceneInfo));
        }

        unifiedOrder.setSignType("MD5");
        String str = SignUtil.sortField(unifiedOrder, "sign");
        str += "&key=" + key;
        String sign = DigestUtil.md5(str).toUpperCase();
        unifiedOrder.setSign(sign);

        String xml = XmlUtil.toXml(unifiedOrder);
        HttpResp httpResp = HttpUtil.postText(URL_UNIFIED_ORDER, xml);
        if(httpResp.getStatusCode() != 200) {
            return null;
        }
        UnifiedOrderResult result = XmlUtil.parse(httpResp.getBody(), UnifiedOrderResult.class);
        if(!UnifiedOrderResult.CODE_SUCCESS.equals(result.getReturnCode())) {
            throw new IllegalStateException(result.getReturnMsg());
        }
        return buildPrepayInfo(unifiedOrder.getAppId(), result.getPrepayId(), key);
    }

    /**
     * 构建预支付信息
     * @param appId     appId
     * @param prepayId  预支付Id
     * @param key       密钥
     * @return          预支付信息
     */
    public static PrepayInfo buildPrepayInfo(String appId, String prepayId, String key) {
        PrepayInfo payInfo = new PrepayInfo();
        payInfo.setAppId(appId);
        payInfo.setNonceStr(UuidUtil.getUUID().substring(0,32));
        payInfo.prepayId(prepayId);
        payInfo.setSignType("MD5");
        payInfo.setTimeStamp(System.currentTimeMillis() / 1000 + "");
        String str = SignUtil.sortField(payInfo, "paySign");
        str += "&key=" + key;
        String sign = DigestUtil.md5(str).toUpperCase();
        payInfo.setPaySign(sign);
        return payInfo;
    }

    /**
     * 订单查询
     *
     * @param orderQuery
     * @return
     */
    public static OrderQueryResult orderQuery(OrderQuery orderQuery) {
        String xml = XmlUtil.toXml(orderQuery);
        HttpResp httpResp = HttpUtil.postText(URL_ORDER_QUERY, xml);
        if(httpResp.getStatusCode() != 200) {
            return null;
        }
        return XmlUtil.parse(httpResp.getBody(), OrderQueryResult.class);
    }

    /**
     * 关闭订单
     *
     * @param closeOrder
     * @return
     */
    public static CloseOrderResult closeOrder(CloseOrder closeOrder) {
        String xml = XmlUtil.toXml(closeOrder);
        HttpResp httpResp = HttpUtil.postText(URL_CLOSE_ORDER, xml);
        if(httpResp.getStatusCode() != 200) {
            return null;
        }
        return XmlUtil.parse(httpResp.getBody(), CloseOrderResult.class);
    }

    /**
     * 申请退款
     *
     * @param refund
     * @return
     */
    public static RefundResult refund(Refund refund) {
        String xml = XmlUtil.toXml(refund);
        HttpResp httpResp = HttpUtil.postText(URL_REFUND, xml);
        if(httpResp.getStatusCode() != 200) {
            return null;
        }
        return XmlUtil.parse(httpResp.getBody(), RefundResult.class);
    }

    /**
     * 查询退款
     *
     * @param refundQuery
     * @return
     */
    public static RefundQueryResult refundquery(RefundQuery refundQuery) {
        String xml = XmlUtil.toXml(refundQuery);
        HttpResp httpResp = HttpUtil.postText(URL_REFUND, xml);
        if(httpResp.getStatusCode() != 200) {
            return null;
        }
        return XmlUtil.parse(httpResp.getBody(), RefundQueryResult.class);
    }

    /**
     * 下载对账单
     *
     * @param downloadBill
     * @return
     */
    public static DownloadBillResult downloadBill(DownloadBill downloadBill) {
        String xml = XmlUtil.toXml(downloadBill);
        HttpResp httpResp = HttpUtil.postText(URL_REFUND, xml);
        if(httpResp.getStatusCode() != 200) {
            return null;
        }
        return XmlUtil.parse(httpResp.getBody(), DownloadBillResult.class);
    }

    /**
     * 交易保障
     *
     * @param report
     * @return
     */
    public static ReportResult report(Report report) {
        String xml = XmlUtil.toXml(report);
        HttpResp httpResp = HttpUtil.postText(URL_REFUND, xml);
        if(httpResp.getStatusCode() != 200) {
            return null;
        }
        return XmlUtil.parse(httpResp.getBody(), ReportResult.class);
    }

}
